<?php

namespace App\Services\Auth;

use App\Repositories\Auth\RoleRepository;
use App\Entities\Auth\Role;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Entities\Auth\Module;
use App\Repositories\Auth\ModuleRepository;
use App\Transformers\Auth\Module\TreeTransformer;
use Pinq\Traversable;
use Spatie\Fractalistic\Fractal;
use Spatie\Fractalistic\ArraySerializer;
use App\Libraries\Common\Tree;
use App\Repositories\Auth\ModuleButtonRepository;

class RoleService
{
    protected $repository;
    protected $moduleRepository;
    protected $moduleButtonRepository;

    public function __construct(RoleRepository $repository, ModuleRepository $moduleRepository, ModuleButtonRepository $moduleButtonRepository)
    {
        $this->repository = $repository;
        $this->moduleRepository = $moduleRepository;
        $this->moduleButtonRepository = $moduleButtonRepository;
    }

    public function getPageList()
    {
        try {
            $request = request();

            $res = $this->repository->paginate($request['limit'])->toArray();

            $data = [
                'code' => 0,
                'msg' => '正在请求中...',
                'count' => $res['total'],
                'data' => $res['data'],
            ];

            return $data;
        } catch (Exception $ex) {
            Log::error('Role getPageList Error', [$ex->getMessage()]);

            return null;
        }
    }

    public function create($data)
    {
        try {
            $role = new Role($data);
            $this->repository->SaveData($role);

            return true;
        } catch (Exception $ex) {
            Log::error('Role Create Error', [$ex->getMessage()]);

            return false;
        }
    }

    public function update($id, $data)
    {
        try {
            $role = new Role($data);
            $this->repository->SaveData($role, $id);

            return true;
        } catch (Exception $ex) {
            Log::error('Role Update id="'.$id.'" Error', [$ex->getMessage()]);

            return false;
        }
    }

    public function show($id)
    {
        try {
            return $this->repository->find($id);
        } catch (Exception $ex) {
            Log::error('Role Load id="'.$id.'" Error', [$ex->getMessage()]);

            return null;
        }
    }

    public function remove($ids)
    {
        $result = [
            'flag' => false,
            'message' => '',
        ];
        DB::beginTransaction();
        try {
            $role = $this->repository->find($ids);
            if (count($role->users) > 0) {
                $result['message'] = '该角色被用户拥有无法删除';
            } else {
                //删除模块权限
                $role->moduleAuthorize()->detach();
                //删除角色
                $role->delete();
                $result['flag'] = true;
            }

            DB::commit();
        } catch (Exception $ex) {
            DB::rollBack();
            Log::error('Module Delete'.$ids.' Error', [$ex->getMessage()]);
        }

        return $result;
    }

    public function savePermission($id, $datas)
    {
        DB::beginTransaction();
        try {
            $role = $this->repository->find($id);
            //删除模块权限
            $role->moduleAuthorize()->detach();
            //删除模块按钮权限
            $role->moduleButtonAuthorize()->detach();

            foreach ($datas as $data) {
                $item = explode('_', $data);
                if ('module' == $item[0]) {
                    $modules[] = $item[1];
                } elseif ('button' == $item[0]) {
                    $buttons[] = $item[1];
                }
            }

            //添加模块权限
            $role->moduleAuthorize()->attach($modules, ['itemtable_type' => Module::class]);
            if (isset($buttons)) {
                //添加模块按钮权限
                $role->moduleButtonAuthorize()->attach($buttons, ['itemtable_type' => ModuleButton::class]);
            }
            DB::commit();
            $this->repository->resetRedisData();

            return true;
        } catch (Exception $ex) {
            DB::rollBack();
            Log::error('role SavePermission'.$id.' Error', [$ex->getMessage()]);

            return false;
        }
    }

    public function getModules($id)
    {
        $data = $this->moduleRepository->all();
        $treeData = Fractal::create()
            ->serializeWith(new ArraySerializer())
            ->collection($data, new TreeTransformer())
            ->toArray();

        $buttons = $this->moduleButtonRepository->all();
        $buttonTreeData = Fractal::create()
            ->serializeWith(new ArraySerializer())
            ->collection($buttons, new \App\Transformers\Auth\ModuleButton\TreeTransformer())
            ->toArray();
        $treeData = array_merge($treeData, $buttonTreeData);

        $authorizes = Traversable::from($this->repository->find($id)->moduleAuthorize->toArray());
        $buttonAuthorizes = Traversable::from($this->repository->find($id)->moduleButtonAuthorize->toArray());

        foreach ($treeData as $key => $item) {
            $has = false;
            if ('module' == $item['type']) {
                $has = $authorizes->where(function ($auth) use ($item) {
                    return $auth['module_id'] == $item['id'];
                })->first();
            } elseif ('button' == $item['type']) {
                $has = $buttonAuthorizes->where(function ($button) use ($item) {
                    return $button['module_button_id'] == $item['id'];
                })->first();
            }
            $treeData[$key]['checked'] = null != $has;
        }

        return Tree::makeTree($treeData, ['expanded_key' => 'open']);
    }
}
